#include <glib.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <glade/glade-xml.h>

#include "totem-plugin.h"
#include "totem-private.h"
#include "totem.h"

#include "totem-lrc.h"
#include "totem-lrc-pad.h"
#include "totem-lrc-func.h"
#include "totem-lrc-down.h"

static lrc_st lrc_line[max_lrc_line+1];
///static gchar *lines[max_lrc_line];


G_DEFINE_TYPE(TotemLrcPad,totem_lrc_pad,gtk_scrolled_window_get_type())

static void totem_lrc_pad_init(TotemLrcPad *pad) ;
static void totem_lrc_pad_class_init(TotemLrcPadClass *pad) ;
static gboolean totem_lrc_pad_timeout(TotemLrcPad *pad);
gint totem_lrc_pad_show_diff(TotemLrcPad *pad);
static void sort_lines(void);
static gboolean totem_lrc_pad_button_release(GtkWidget* treeview,
                               GdkEventButton* event,
                               TotemLrcPad *pad);

static void totem_lrc_pad_about_item(GtkMenuItem *menuitem,TotemLrcPad *pad);
static void totem_lrc_pad_reload_item(GtkMenuItem *menuitem,TotemLrcPad *pad);
static void totem_lrc_pad_search_item(GtkMenuItem *menuitem,TotemLrcPad *pad);

static gboolean totem_lrc_pad_timeout(TotemLrcPad *pad)
{
	switch(pad->lts){
	case LRC_RUN:
		totem_lrc_pad_show_diff(pad);
	break;
	case LRC_STOP:
		pad->timeout_id = 0;
		lmp_debug("***Stop timeout !***");
		return FALSE;
	break;
	case LRC_RELOAD:
		totem_lrc_pad_load_lrc(pad);
		pad->lts = LRC_RUN;
	break;
	default:
	break;
	}

	return TRUE;
}

static void totem_lrc_pad_class_init(TotemLrcPadClass *klass)
{
	klass->timeout = totem_lrc_pad_timeout;
}

static void totem_lrc_pad_init(TotemLrcPad *pad)
{
	
}

GtkWidget *totem_lrc_pad_new(TotemLrcPlugin *pi)
{
	GtkTextBuffer* buffer ;
	GtkWidget *view ;
	GtkScrolledWindow *scroll ;
	GtkTextTag *tag;
	TotemLrcPad *pad ;

	lmp_debug("");
	pad = g_object_new (TOTEM_LRC_PAD_TYPE,
				    "hadjustment", NULL,
				    "vadjustment", NULL,
				    NULL);
	scroll = GTK_SCROLLED_WINDOW(pad);
	view = gtk_text_view_new ();

	lmp_debug("");
	gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view),FALSE);
	gtk_text_view_set_justification(GTK_TEXT_VIEW(view),GTK_JUSTIFY_CENTER);
	gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(view),2);
	gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW(view),2);
	gtk_text_view_set_pixels_inside_wrap(GTK_TEXT_VIEW(view),2);
	gtk_container_set_resize_mode(GTK_CONTAINER(view), GTK_RESIZE_PARENT);

	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
	gtk_container_set_resize_mode(GTK_CONTAINER(scroll),GTK_RESIZE_PARENT);
	gtk_scrolled_window_set_shadow_type(
	                                    GTK_SCROLLED_WINDOW (scroll),
	                                    GTK_SHADOW_OUT);
	gtk_scrolled_window_set_policy (
	               GTK_SCROLLED_WINDOW (scroll),
	               GTK_POLICY_NEVER	/*GTK_POLICY_AUTOMATIC*/,
	               ///GTK_POLICY_NEVER
	               GTK_POLICY_AUTOMATIC
	               );

	gtk_container_add (GTK_CONTAINER (scroll), view);
//	gtk_scrolled_window_add_with_viewport(scroll,view);
	gtk_widget_show_all(scroll);

	tag = gtk_text_buffer_create_tag (buffer,
	                                 "blue_foreground",
	                                 "foreground",
	                                 "blue",
	                                  NULL);
	gtk_text_buffer_set_text (buffer,
	                          _("\n\n\n\n      Lyricshow show lyric for ME      \n"),
	                         -1);

	g_signal_connect(GTK_WIDGET(view),
	                "button-release-event",
	                GTK_SIGNAL_FUNC(totem_lrc_pad_button_release),
	                pad);

	g_signal_connect(GTK_WIDGET(view),
	                "button-press-event",
	                GTK_SIGNAL_FUNC(totem_lrc_pad_button_release),
	                pad);

	pad->view = view;
	pad->pi = pi;
	pad->buf = buffer ;
	pad->tag = tag ;
	pad->lts = LRC_STOP;
	pad->download_dialog = NULL;
	return GTK_WIDGET(pad);
}

void totem_lrc_pad_run(TotemLrcPad *pad)
{
	if(pad->lts == LRC_RUN)
		return ;
	if(!pad->timeout_id)
		pad->timeout_id = 
			g_timeout_add(250,
			             TOTEM_LRC_PAD_GET_CLASS(pad)->timeout,
			             pad);
	pad->lts = LRC_RUN ;
	lmp_debug("");
}


static void totem_lrc_pad_about_item(GtkMenuItem *menuitem,TotemLrcPad *pad)
{
	gchar *authors[]={
	"wkt <wkt55555@163.com>",
	NULL,
	};
	gchar *copyright = "Copyright © 2008 wkt";
	gchar *description = _("Plugin for search, dwonload and show lyric in Totem");
	gtk_show_about_dialog (GTK_WINDOW (pad->pi->totem->win),//GTK_WINDOW (win),
	                      "program-name","LrcShow",
	                      "version",LRC_VERSION,
	                      "copyright",copyright,
	                      "comments",description,
	                      "authors",authors,
	                      "logo-icon-name",GTK_STOCK_ABOUT,
	                      "website-label",_("Welcome to Project homepage\nBugs report to wkt55555@163.com"),
	                       ///"欢迎访问项目主页\n错误报告:wkt55555@163.com",
	                      "website","http://tlrcshow.googlecode.com/",
	                      NULL);
	lmp_debug("");
}

static gboolean totem_lrc_pad_button_release(GtkWidget* treeview,
                               GdkEventButton* event,
                               TotemLrcPad *pad)
{
//	  lmp_debug("");
	if (event->type == GDK_BUTTON_RELEASE  &&  event->button == 3){
		lmp_debug("right.");
		static GtkWidget *menu = NULL;
		GtkWidget *search;
		GtkWidget *reload;
		GtkWidget *about;
		GtkWidget *sep;

		if(!menu){
			menu = gtk_menu_new();
			search = gtk_menu_item_new_with_mnemonic(_("_Search online"));
			reload = gtk_menu_item_new_with_mnemonic(_("_Reload"));
			about = gtk_menu_item_new_with_mnemonic(_("_About"));
			sep = gtk_separator_menu_item_new();

			gtk_menu_shell_append(GTK_MENU_SHELL(menu),search);
			gtk_menu_shell_append(GTK_MENU_SHELL(menu),reload);
			gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
			gtk_menu_shell_append(GTK_MENU_SHELL(menu),about);

			g_signal_connect(GTK_WIDGET(search),
			                "activate",
			                G_CALLBACK(totem_lrc_pad_search_item),
			                pad);
			g_signal_connect(GTK_WIDGET(reload),
			                 "activate",
			                 G_CALLBACK(totem_lrc_pad_reload_item),
			                 pad);
			g_signal_connect(GTK_WIDGET(about),
			                 "activate",
			                 G_CALLBACK(totem_lrc_pad_about_item),
			                 pad);
 		}
		gtk_widget_show_all(GTK_WIDGET(menu));
		gtk_menu_popup(GTK_MENU(menu),
		           NULL,
		           NULL,
		           NULL,
		           NULL, 1,
		           gtk_get_current_event_time());
	}
	if (event->type == GDK_BUTTON_RELEASE  &&  event->button == 1){
		GtkTextIter iter;
		gint trail;
		gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(treeview),&iter,event->x,event->y);
		//gtk_text_view_get_iter_at_position(GTK_TEXT_VIEW(treeview),&iter,&trail,event->x,event->y);
		trail = gtk_text_iter_get_line (&iter);
		totem_action_seek_time(pad->pi->totem,lrc_line[trail].tm);
		g_printerr("lrc_line[%d]{.tm=%lld,.pt=%d,.n=%d}\n",trail,lrc_line[trail].tm,lrc_line[trail].pt,lrc_line[trail].n);
		g_printerr("curtime:%lld\n",totem_get_current_time(pad->pi->totem));
	}

	return TRUE;
}

static void on_gtk_entry(GtkEntry *entry,GtkButton *button)
{
	gtk_button_clicked(button);
}

static void totem_lrc_pad_reload_item(GtkMenuItem *menuitem,TotemLrcPad *pad)
{
	lmp_debug("reload");
	pad->lts = LRC_RELOAD ;
}

static void on_bt_cancel(GtkButton *button,GtkDialog *dialog)
{
	gtk_dialog_response(dialog,GTK_RESPONSE_DELETE_EVENT);
}

static void on_bt_search(GtkButton *button,CallData *cdata)
{
	const gchar *artist;
	const gchar *title;

	artist = gtk_entry_get_text(cdata->artist);
	title = gtk_entry_get_text(cdata->title);

	MataInfo *m = cdata->pad->pi->minfo;
	g_free(m->artist);
	m->artist = g_strdup(artist);

	g_free(m->title);
	m->title = g_strdup(title);
	gtk_widget_set_sensitive(GTK_WIDGET(button),FALSE);
	totem_lrc_plugin_send_event(cdata->pad->pi,TASK_GO_SEARCH);
}

static void on_bt_download(GtkButton *button,CallData *cdata)
{
	GtkTreeModel *model;
	GtkTreeIter iter;
	unsigned int index =0;
	gchar *url;

	MataInfo *m = cdata->pad->pi->minfo;

	gtk_widget_set_sensitive(GTK_WIDGET(button),FALSE);

	if(m->lyricfile_w && gtk_tree_selection_get_selected(cdata->select,&model,&iter)){
		gtk_tree_model_get (GTK_TREE_MODEL(model),
		                   &iter,
		                   COL_NUM,&index,
		                   COL_URL,&url,
		                   -1);
		g_free(m->url);
		m->url = url;
		g_print("m->url = %p:%s\n",m->url,m->url);
/*
		LyricId *id = g_slist_nth_data(m->list,index);
		g_print("id->url = %p:%s\n",id->url,id->url);
		if(m->url == id->url){
			lmp_debug("Happy to be same .");
		}
*/
 		totem_lrc_plugin_send_event(cdata->pad->pi,TASK_GO_DOWNLOAD);
	}else{
		gtk_widget_set_sensitive(GTK_WIDGET(button),TRUE);
		GtkWidget *msg = gtk_message_dialog_new_with_markup(NULL,
		                                        GTK_DIALOG_DESTROY_WITH_PARENT |GTK_DIALOG_MODAL,
		                                        GTK_MESSAGE_ERROR,
		                                        GTK_BUTTONS_CLOSE,
		                                        _("<b>Artist: %s,Title: %s</b> ."),
		                                        m->artist,
		                                        m->title);
		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
		                                        _("Can't save lyrics"));
		gtk_dialog_run(GTK_DIALOG(msg));
		gtk_widget_destroy(msg);
		totem_lrc_plugin_send_event(cdata->pad->pi,TASK_DOWNLOAD_FAIL);
	}
}

static void on_list_click(GtkTreeView *tree_view, 
                          GtkTreePath *path,
                          GtkTreeViewColumn *column,
                          GtkButton *button)
{
	gtk_widget_set_sensitive(GTK_WIDGET(tree_view),FALSE);
	gtk_button_clicked(button);
}

static void totem_lrc_fill_model(TotemLrcPad *pad,CallData *cdata)
{
	GtkTreeModel *model;
	GtkTreeIter iter;
	gint i=0;
	model = gtk_tree_view_get_model(cdata->treeview);
	if(!model){
		lmp_debug("mode == NULL !");
		return ;
	}
	gtk_list_store_clear(GTK_LIST_STORE(model));
	GSList *l = pad->pi->minfo->list;
	for(;l;l= l->next){
		LyricId *id = l->data;
		gtk_list_store_append (GTK_LIST_STORE (model), &iter);
		gtk_list_store_set(GTK_LIST_STORE (model), &iter,
		                   COL_NUM,id->no,
		                   COL_ARTIST,id->artist?id->artist:"",
		                   COL_TITLE,id->title?id->title:"",
		                   COL_URL,id->url?id->url:"htpp://",
		                   -1);
	}
	lmp_debug("return");
}

static void totem_lrc_pad_search_item(GtkMenuItem *menuitem,TotemLrcPad *pad)
{
	GladeXML  *xml;
	GtkWidget *dialog;
	GtkWidget *down;
	GtkWidget *cancel;
	GtkWidget *search;
	GtkWidget *treeview;
	GtkTreeViewColumn* col;
	GtkCellRenderer* renderer;
	GtkListStore *model;
	static CallData cdata;

	gchar *ui = totem_plugin_find_file((TotemPlugin*)pad->pi,"down.glade");
	xml = glade_xml_new(ui,NULL,NULL);
	g_free(ui);
	ui = NULL;

	treeview = glade_xml_get_widget(xml,"treeview");
	down = glade_xml_get_widget(xml,"bt_download");
	cancel = glade_xml_get_widget(xml,"bt_cancel");
	search = glade_xml_get_widget(xml,"bt_search");
	dialog = glade_xml_get_widget(xml,"Lyrics_download");
	cdata.artist = glade_xml_get_widget(xml,"artist");
	cdata.title = glade_xml_get_widget(xml,"title");
	cdata.pad = pad;
	pad->download_dialog = dialog;
	cdata.treeview = treeview;
	g_object_unref(xml);

	totem_lrc_plugin_set_artist_title(pad->pi);///update things
	gchar *str = pad->pi->minfo->artist;
	if(str)
		gtk_entry_set_text(cdata.artist,str);
	str = pad->pi->minfo->title;
	lmp_debug("str=%p:%s",str,str);
	if(str)
		gtk_entry_set_text(cdata.title,str);
	str = NULL;

	model = gtk_list_store_new (COL_LAST,G_TYPE_INT, G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING);

///	lmp_debug("model :%p,treeview:%p",model,treeview);
	gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (model));

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes (_("Number"),
	                                                renderer,
	                                                "text",COL_NUM,
	                                                 NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW (treeview), col);

	col = gtk_tree_view_column_new_with_attributes (_("Artist"),
	                                                renderer,
	                                               "text",COL_ARTIST,
	                                                NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW (treeview), col);

	col = gtk_tree_view_column_new_with_attributes (_("Title"),
	                                                renderer,
	                                                "text", COL_TITLE,
	                                                NULL);
	gtk_tree_view_append_column(GTK_TREE_VIEW (treeview), col);

	cdata.select = gtk_tree_view_get_selection(GTK_TREE_VIEW (treeview));

	gtk_tree_selection_set_mode(cdata.select, GTK_SELECTION_SINGLE);
	g_signal_connect(down,
	                 "clicked",
	                G_CALLBACK(on_bt_download),&cdata);

	g_signal_connect(cancel,
	                "clicked",
	                G_CALLBACK(on_bt_cancel),dialog);

	g_signal_connect(cdata.artist,
	                "activate",
	                G_CALLBACK(on_gtk_entry),search);

	g_signal_connect(cdata.title,
	                "activate",
	                G_CALLBACK(on_gtk_entry),search);

	g_signal_connect(search,
	                "clicked",
	                G_CALLBACK(on_bt_search),&cdata);

/*
	g_signal_connect(dialog,
	                "response",
	                G_CALLBACK(on_bt_dialog_response),&cdata);
*/

	g_signal_connect(treeview, 
	                "row-activated", 
	                G_CALLBACK(on_list_click), down);

	gint id = DIALOG_NOTHINGS;
	while(id != GTK_RESPONSE_DELETE_EVENT){
		id = gtk_dialog_run(GTK_DIALOG(dialog));
		switch(id){
		case GTK_RESPONSE_DELETE_EVENT :
			gtk_widget_destroy(pad->download_dialog);
			pad->download_dialog = NULL;
		break;
		case DIALOG_DOWNLOAD:
			gtk_widget_set_sensitive(treeview,TRUE);
			gtk_widget_set_sensitive(down,TRUE);
		break;
		case DIALOG_SEARCH:
			totem_lrc_fill_model(pad,&cdata);
			gtk_widget_set_sensitive(search,TRUE);
		break;
		default:
		break;
		}
	}
//	totem_lrc_plugin_send_event(pad->pi,TASK_GO_SEARCH);
}

void totem_lrc_pad_response(TotemLrcPad *pad,DialogId id)
{
	if(pad->download_dialog)
		gtk_dialog_response(pad->download_dialog,id);
}

static void sort_lines(void)
{
	lrc_st tmp={0,0};
	gint i=0,j=0;
	tmp=lrc_line[i];
	while(lrc_line[i].tm>-1){
		j=i+1;
		while(lrc_line[j].tm>-1){
			if(lrc_line[i].tm>lrc_line[j].tm){
				tmp=lrc_line[i];
				lrc_line[i]=lrc_line[j];
				lrc_line[j]=tmp;
			}
			j++;
		}
		i++;
	}
}

gint totem_lrc_pad_show_diff(TotemLrcPad *pad)
{
//lmp_debug("tm=%lld",tm);
	
	GtkTextIter start, end;
	GtkTextBuffer *buffer = pad->buf;
	GtkTextView *view = pad->view;
	GtkTextTag *tag = pad->tag ;
	gint index=0;
	static gint64 oldtm = 0;
	gint64 tm,tm1,tm2;
	tm =  totem_get_current_time(pad->pi->totem);
	if(oldtm==tm)
		return index;
	oldtm = tm;
	tm1 = lrc_line[index].tm;
	while(tm1>-1&&pad->lts == LRC_RUN){
		tm2 = lrc_line[index+1].tm;
		if(tm1&&(tm2>=tm||tm2<0)&&tm>=tm1){ //
			gdk_threads_enter();
			gtk_text_buffer_get_start_iter(buffer,&start);
			gtk_text_buffer_get_end_iter (buffer,&end);
			gtk_text_buffer_remove_all_tags(buffer,&start,&end);
			gtk_text_buffer_get_iter_at_line(buffer,&start,index);
			gtk_text_buffer_get_iter_at_line(buffer,&end,index+1);
			gtk_text_buffer_apply_tag (buffer, tag, &start, &end);

			if(index%3==2)
				gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(view),&start,0.1,TRUE,0.3,0.4);
//			g_print("index=%d--%lld:%lld\n",index,tm,lrc_line[index].tm);
			gdk_flush();
			gdk_threads_leave();
			return index;
		}
		index++;
		tm1 = lrc_line[index].tm;
	}
	return index;
}

void totem_lrc_pad_clear(TotemLrcPad *pad)
{
	lmp_debug("clear buffer");
	gtk_text_buffer_set_text(pad->buf,"",-1);
	lmp_debug("buffer cleaned");
}

void totem_lrc_pad_set_text(TotemLrcPad *pad,gchar *text)
{
	GtkTextIter start;
	lmp_debug("set text");
	gtk_text_buffer_get_start_iter(pad->buf,&start);
	gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(pad->view),
	                          &start,
	                          0.1,
	                          TRUE,
	                          0.3,
	                          0.4);
	gtk_text_buffer_set_text(pad->buf,text,-1);
	lmp_debug("text seted");
}

void fuck_lrc_line(void)
{
	int i=0;
	FILE *f=fopen("/tmp/log.f","w");
	while(lrc_line[i].tm>-1){
		fprintf(f,"pt=%d:tm=%lld\n",lrc_line[i].pt,lrc_line[i].tm);
		i++;
	}
	fclose(f);
}

static gboolean load_lrc_into_mem(TotemLrcPad *pad,gchar *lrc,gchar **lines)
{
	FILE *f;
	size_t len = 0,i=0,j=0;
	char *line= NULL;
	char *tmp = NULL;

	lmp_debug("try to load %s",lrc);
	f=fopen(lrc,"r");
	if(!f){
		fprintf(stderr,"fopen():%s:%s.\n",lrc,strerror(errno));
		return FALSE;
	}

	lrc_line[j].pt = i;
	lrc_line[j++].tm = 0;
	lrc_line[j].tm = -1;
	lines[i++] = g_strdup("");

	while(getline(&line,&len,f)!=-1&&j<max_lrc_line){
		if(*line!='[')
			continue;
		char *head = tmp = totem_lrc_plugin_encode_to_utf8(pad->pi,line+1);
		set_a_to_b(tmp,'\n',0);//拿掉换行符,有的换行符在textview上是两个的效果。
		set_a_to_b(tmp,'\r',0);//在这里去掉行符有点不好

		if(*tmp<'0'||*tmp>'9'){//处理没有时间的行
			lines[i] = g_strdup(get_addr(tmp,':'));//仅显示：后的文字.
			lrc_line[j].tm = 0;
			lrc_line[j++].pt = i;
			set_a_to_b(lines[i++],']',' ');
			lrc_line[j].tm = -1;
			goto ex;
		}

		do{///many time point at one line
			lrc_line[j].tm = read_time_at_line(tmp);
			lrc_line[j++].pt = i;
			lrc_line[j].tm=-1;
///			g_print("tm =%lld tmp = %s\n",lrc_line[j-1].tm,tmp);
			tmp = get_addr(tmp,'[');
///			g_print("tm =%lld tmp = %s\n",lrc_line[j-1].tm,tmp);
			if(tmp&&*tmp&&(tmp[1]>'9' || tmp[1] <'0'))
				break; 
		}while(tmp&&j<max_lrc_line);

		lines[i++] = g_strdup(get_addr_last(head,']'));
		ex: g_free(head);
///		g_print("i=%d,%s\n",i-1,lines[i-1]);
	}
	fuck_lrc_line();
	if(line)
		free(line);
	fclose(f);
// lmp_debug("%s",tmp);
	return i>2; /// legality lyric will true i>2.
}

gboolean totem_lrc_pad_load_lrc(TotemLrcPad *pad)
{
	gsize j=0;
	GtkTextIter old;

	const gchar *file = pad->pi->minfo->lyricfile_r;
	lmp_debug("%s",file);
	gchar *lines[max_lrc_line+1] = {0};
	if(file >(void*)0x1000&&!load_lrc_into_mem(pad,file,lines)){
		return FALSE;
	}

	sort_lines();//根据时间给指向各个字串的索引排序
	totem_lrc_pad_clear(pad);//清空textveiw
	gtk_text_buffer_get_iter_at_offset (pad->buf, &old, 0);

	while(lrc_line[j].tm>-1){

		gchar *lrcstr = lines[lrc_line[j].pt];
		gtk_text_buffer_insert (pad->buf, &old,lrcstr,-1);
		gtk_text_buffer_insert (pad->buf, &old,"\n",-1);//所有的行都没有换行符，所以都需要加上。

		j++;
	}

	gtk_text_buffer_insert (pad->buf, &old,"\n\n\n",-1);

	j=0;
	while(j<=max_lrc_line){
		g_free(lines[lrc_line[j].pt]);
		lines[lrc_line[j++].pt] = NULL;
	}
	lmp_debug("");
	return TRUE;
}

